Width: lt 150 characters Height: lte 20 lines
Sub-blocks should be function calls
A function should go no more than one level of abstraction below the function name. Or If a function name is simply a restatement of it’s implementation, then it is unnecessary.
Each level of abstraction should have it’s own function, each invoking only one level below itself.
Switch statements are acceptable in abstract factories generating polymorphic objects
Longer, more descriptive names are desirable
Fewer is better. Arguments are a different level of abstraction. Testing is combinatorially complex.
function fileExists(string $path): bool;
function readFile(string $path): File;
function saveFailed(stdClass $record): void;
Better multiple functions than functions with flags.
convert to monadic functions by converting to member function or creating a separate class to wrap
each new argument is combinatorially more complicated
reduce number of args by grouping args together into domain objects
// worse
function makeCircle(float $x, float $y, float $radius): Circle;
// better
function makeCircle(Point $point, float $radius): Circle;
functions accepting argument lists technically collapse that list to a single argument, e.g.
// monadic
function concat(string ...$args): string;
// dyadic
function format(string $template, string ...$args): string;
function assertExpectedEqualsActual($expected, $actual): void;
side effects may cause unexpected state changes temporal couplings
in OO, this is the output argument
read state, write state, not both
if (set('foo', 'bar'))
// vs
if (propertyExists('foo'))
setProperty('foo', 'bar');
exceptions propagate naturally, return codes do not
try/catch blocks bifercate between normal processing and error processing; simplify the logic as much as possible
functions do one thing => error handling is one thing; unique functions for error cases
everything in programming is an attempt to reduce duplication
Dijkstra’s structured programming rules are not relevant in small functions